package cc.rboot.fsm.core;

import cc.rboot._core.holder.AppContextHolder;
import cc.rboot.fsm.error.FsmMappingNotFoundException;
import org.springframework.context.annotation.DependsOn;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@DependsOn("appContextHolder")
public abstract class AbstractFsmState<T> implements IFsmState<T> {

    private final Map<IFsmEvent, IFsmState<T>> MAPPING_MAP = new ConcurrentHashMap<>();

    @Resource
    AppContextHolder appContextHolder;

    @PostConstruct
    public void construct() {
        this.init();
    }

    @Override
    public IFsmState<T> transfer(Class<? extends IFsmEvent> eventClass, Object... params) {
        IFsmEvent event = AppContextHolder.getBean(eventClass);

        if(event ==null && appContextHolder != null) {
            event = appContextHolder.getBean(eventClass);
        }

        if (this.MAPPING_MAP.containsKey(event)) {
            event.handler(params);
            return this.MAPPING_MAP.get(event);
        }
        throw new FsmMappingNotFoundException(params);
    }

    /**
     * 请在实现类的init方法中调用
     * 注入该业务相关的所有映射关系，当前状态在经过什么样的事件后转换到的下一个状态是什么
     */
    protected void inject(Class<? extends IFsmEvent> eventClass, Class<? extends IFsmState<T>> nextStateClass) {
        IFsmEvent event = AppContextHolder.getBean(eventClass);

        if(event ==null && appContextHolder != null) {
            event = appContextHolder.getBean(eventClass);
        }

        IFsmState<T> nextState = AppContextHolder.getBean(nextStateClass);

        if(nextState ==null && appContextHolder != null) {
            event = (IFsmEvent) appContextHolder.getBean(nextStateClass);
        }

        this.MAPPING_MAP.put(event, nextState);
    }
}
